package itsm.isperp.framework.security.access.intercept;

import itsm.isperp.framework.core.context.ContextHolder;
import itsm.isperp.framework.security.license.LicenseException;
import itsm.isperp.framework.security.license.LicenseUtils;

import java.io.IOException;
import java.util.Collection;

import javax.servlet.ServletException;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.intercept.InterceptorStatusToken;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.context.HttpRequestResponseHolder;

/**
 * @since 1.0
 */
public class UrlSecurityInterceptor extends FilterSecurityInterceptor implements
		ApplicationContextAware {
	private static final String FILTER_APPLIED = "__spring_security_filterSecurityInterceptor_filterApplied";

	private Collection<SecurityInterceptor> securityInterceptorCollection;

	public void invoke(FilterInvocation fi) throws IOException,
  ServletException {
    String url = fi.getRequestUrl();
    if (url.indexOf("/sso") == 0) {
      fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
      return;
    }
    else if ((fi.getRequest() != null)
        && (fi.getRequest().getAttribute(FILTER_APPLIED) != null)
        && isObserveOncePerRequest()) {
      fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
    } else {

      if (!ContextHolder.isLogin()) {
        throw new AccessDeniedException("请先登录！");
      }
      if (!LicenseUtils.validata()) {
        throw new LicenseException("非法授权！");
      }

      if (fi.getRequest() != null) {
        fi.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE);
      }

      // preferenceService.getAuthorityStrategy().equals("U")
      // 表示当前系统采用基于URL的权限管控方式
      InterceptorStatusToken token = null;
      try {
        token = super.beforeInvocation(fi);

      } catch (Exception ex) {
        for (SecurityInterceptor interceptor : securityInterceptorCollection) {
          interceptor
              .authorizationFailure(new HttpRequestResponseHolder(
                  ContextHolder.getRequest(), ContextHolder
                      .getResponse()));
        }
        throw new ServletException(ex);
      }

      try {
        fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
      } finally {
        super.finallyInvocation(token);
      }
      super.afterInvocation(token, null);
}
}

	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		securityInterceptorCollection = applicationContext.getBeansOfType(
				SecurityInterceptor.class).values();
	}
}
